﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using System.Reflection;

namespace MefTZAddin
{
    public static class TimeZoneLocationService
    {
        // Cached collection of mappings between Olson time zone names and Windows time zone names
        private static Dictionary<string, OlsonTimeZoneMapping> mappings = new Dictionary<string, OlsonTimeZoneMapping>();

        static TimeZoneLocationService()
        {
            CacheMappings();
        }

        // http://www.earthtools.org/webservices.htm
        // http://www.geonames.org
        public static double? GetBaseUtcOffsetByCoordinates(double latitude, double longitude)
        {
            // http://www.geonames.org/export/web-services.html
            XDocument doc = XDocument.Load("http://ws.geonames.org/timezone?lat=" + latitude + "&lng=" + longitude + "&style=full");
            XElement tzInfo = (from node in doc.Elements("geonames").Elements("timezone")
                               select node).FirstOrDefault();

            //string timezoneId = (string)tzInfo.Element("timezoneId");
            if (tzInfo == null) return null;
            double gmtOffset = Convert.ToDouble(tzInfo.Element("gmtOffset").Value);

            /*<timezone>
                <countryCode>ES</countryCode>
                <countryName>Spain</countryName>
                <lat>39.5</lat>
                <lng>-5.97</lng>
                <timezoneId>Europe/Madrid</timezoneId>
                <dstOffset>2.0</dstOffset>
                <gmtOffset>1.0</gmtOffset>
                <rawOffset>1.0</rawOffset>
                <time>2009-11-02 01:31</time>
            </timezone>*/
            return gmtOffset;
        }

        public static TimeZoneInfo GetTimeZoneInfoByCoordinates(double latitude, double longitude)
        {
            // http://www.geonames.org/export/web-services.html
            XDocument doc = XDocument.Load("http://ws.geonames.org/timezone?lat=" + latitude + "&lng=" + longitude + "&style=full");
            XElement tzInfo = (from node in doc.Elements("geonames").Elements("timezone")
                               select node).FirstOrDefault();

            if (tzInfo == null) return null;

            return FindByTZID(tzInfo.Element("timezoneId").Value);
        }

        public static TimeZoneInfo FindByTZID(string tzid)
        {
            OlsonTimeZoneMapping tzm = null;
            mappings.TryGetValue(tzid, out tzm);
            if (tzm != null)
                return TimeZoneInfo.FindSystemTimeZoneById(tzm.WindowsName);
            else 
                return null;
        }

        private static void CacheMappings()
        {
            Assembly a = Assembly.GetExecutingAssembly();

            using (System.IO.StreamReader sr = new System.IO.StreamReader(a.GetManifestResourceStream("MefTZAddin.TZDB.csv")))
            {
                string row;
                string[] col;
                OlsonTimeZoneMapping tzm;
                while ((row = sr.ReadLine()) != null)
                {
                    col = row.Split(',');
                    tzm = new OlsonTimeZoneMapping{OlsonName = col[0], WindowsName = col[1]};
                    if( !mappings.ContainsKey(tzm.OlsonName) )
                        mappings.Add(tzm.OlsonName, tzm);

                    if (!mappings.ContainsKey(tzm.WindowsName))
                        mappings.Add(tzm.WindowsName, tzm);
                }
            }
        }
    }

    class OlsonTimeZoneMapping
    {
        public string OlsonName;
        public string WindowsName;
    }
}
